﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Jemgine.Engine
{
    public class ScriptModule : Module
    {
        class FireRecord
        {
            public int Delay;
            public Data.ScriptNode Target;
            public int Terminal;
            public Data.ScriptPayload Payload;
       }

        Queue<FireRecord> FireList = new Queue<FireRecord>();
        List<FireRecord> DelayFireList = new List<FireRecord>();
        List<FireRecord> Recycled = new List<FireRecord>();

        public override void EndSimulation()
        {
            foreach (var Item in FireList) Recycled.Add(Item);
            foreach (var Item in DelayFireList) Recycled.Add(Item);

            FireList.Clear();
            DelayFireList.Clear();
        }

        private FireRecord GetFireRecord()
        {
            FireRecord R = null;
            if (Recycled.Count >= 1)
            {
                R = Recycled[Recycled.Count - 1];
                Recycled.RemoveAt(Recycled.Count - 1);
            }
            else
                R = new FireRecord();
            return R;
        }

        public override void BeginSimulation()
        {
        }

        public override void Update(float ElapsedSeconds)
        {
            for (int I = 0; I < DelayFireList.Count; )
            {
                if (DelayFireList[I].Delay <= 1)
                {
                    FireList.Enqueue(DelayFireList[I]);
                    DelayFireList.RemoveAt(I);
                }
                else
                {
                    DelayFireList[I].Delay -= 1;
                    ++I;
                }
            }

            for (int Loop = 0; Loop < 8; ++Loop)
            {
                int Count = FireList.Count;
                for (int i = 0; i < Count; ++i)
                {
                    FireRecord F = FireList.Dequeue();
                    F.Target.FireTerminal(F.Terminal, F.Payload);
                    Recycled.Add(F);
                }
            }
        }

        public void FireTerminal(Data.InputTerminal Terminal, Data.ScriptPayload Payload, int Delay)
        {
            if (Terminal.Me == null) return;
            if (!Terminal.Me.Enabled) return;

            FireRecord Record = GetFireRecord();
            Record.Target = Terminal.Me;
            Record.Terminal = Terminal.LocalID;
            Record.Payload = Payload;
            Record.Delay = Delay;

            if (Record.Delay >= 1)
                DelayFireList.Add(Record);
            else
                FireList.Enqueue(Record);
        }
    }
}
